#ifndef _GWBASE_BASE_LINK_LIST_H_
#define _GWBASE_BASE_LINK_LIST_H_

#include <stddef.h>
#include <assert.h>

namespace dicom {

template <class T>
class LinkNode {
 public:
  LinkNode() : prev_(this), next_(this) {}
  virtual ~LinkNode() {}

  void InsertAfter(LinkNode* t) {
    assert(t != this);
    this->prev_ = t;
    t->next_->prev_ = this;
    this->next_ = t->next_;
    t->next_ = this;

    assert(this->prev_ == t);
    assert(t->next_ == this);
    assert(this->next_->prev_ == this);
  }

  void InsertBefore(LinkNode* t) {
    assert(t != this);
    this->next_ = t;
    this->prev_ = t->prev_;
    t->prev_ = this;
    this->prev_->next_ = this;

    assert(this->next_ == t);
    assert(t->prev_ == this);
    assert(this->prev_->next_ == this);
  }

  void RemoveFromList() {
    if (orphan()) return;

    this->prev_->next_ = this->next_;
    this->next_->prev_ = this->prev_;
    this->prev_ = this;
    this->next_ = this;
    assert(orphan());
  }

  bool orphan() const { return this->prev_ == this; }
  LinkNode<T>* next() const { return next_; }
  LinkNode<T>* prev() const { return prev_; }

  const T* value() const { return static_cast<const T*>(this); }
  T* value() { return static_cast<T*>(this); }

 protected:
  LinkNode<T>* prev_;
  LinkNode<T>* next_;
};

template <class T>
class LinkList {
 public:
  LinkList() {}
  ~LinkList() {}

  void append(LinkNode<T>* n) { n->InsertBefore(&sentinal_); }

  bool empty() const { return sentinal_.orphan(); }
  LinkNode<T>* begin() const { return sentinal_.next(); }
  const LinkNode<T>* end() const { return &sentinal_; }

  LinkNode<T>* rbegin() const { return sentinal_.prev(); }
  const LinkNode<T>* rend() const { return &sentinal_; }

 private:
  LinkNode<T> sentinal_;
};
};

#endif  // _GWBASE_BASE_LINK_LIST_H_
